#include <string>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include "strings.h"
#include <assert.h>

#include <leveldb/db.h>
#include "db_impl.h"

using namespace std;

DBImpl::DBImpl(std::string db_path){
    this->options.create_if_missing = true;    
    this->write_options.sync = true;
    this->status = leveldb::DB::Open(this->options, db_path, &db);
    if ( !this->status.ok() ) {
        printf("%s\n", status.ToString().c_str());
        exit(1);
    }
}

DBImpl::~DBImpl(){
    delete db;
}

int DBImpl::set(std::string key, std::string val){    
    status = db->Put(write_options, key, val);
    if(!status.ok()){
        return 0;
    }
    return 1;
}

int DBImpl::get(std::string key, std::string *val){
    status = db->Get(leveldb::ReadOptions(), key, val);
    if (!status.ok()) {
        printf("%s\n", status.ToString().c_str());
        return 0;
    }    
    return 1;
}

int DBImpl::incr(std::string key, int64_t by, int64_t *new_val){
    std::string old;
    int ret = this->get(key, &old);
    if(ret == -1){
        return -1;
    }else if(ret == 0){
        *new_val = by;
    }else{
        *new_val = str_to_int64(old) + by;
        if(errno != 0){
            return 0;
        }
    }

    std::string buf = key;
    leveldb::Status s = this->db->Put(write_options, buf, str(*new_val));    
    if(!s.ok()){
            //log_error("del error: %s", s.ToString().c_str());
            return -1;
    }
    return 1;
}

int DBImpl::scan(std::string key, std::string start, std::string end, uint64_t limit){
    leveldb::Iterator* it = db->NewIterator(leveldb::ReadOptions());
    for (it->SeekToFirst(); it->Valid(); it->Next()) {
        printf("%s : %s \n", it->key().ToString().c_str(), it->value().ToString().c_str());
    }
    if(!it->status().ok()){ // Check for any errors found during the scan
        return 0;
    }
    return 1;
}   